package com.yy.m3u8tool.parser;

import androidx.annotation.IntDef;
import androidx.annotation.StringDef;
import com.yy.m3u8tool.parser.ffmpeg.FfmpegM3u8Jni;
import com.yy.m3u8tool.parser.ffmpeg.FfmpegM3u8Parser;
import com.yy.m3u8tool.parser.java.JavaParser;
import com.yy.m3u8tool.utils.LogUtil;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import org.json.JSONObject;

public class M3u8Parser {

  @IntDef({ConvertType.TYPE_FFMPEG, ConvertType.TYPE_JAVA})
  @Retention(RetentionPolicy.SOURCE)
  public @interface ConvertType{
    int TYPE_FFMPEG=1;
    int TYPE_JAVA=2;
  }

  @StringDef({ConvertState.STATUS_READY,ConvertState.STATUS_CONVERTING,
      ConvertState.STATUS_COMPLETE,ConvertState.STATUS_FORMAT,
      ConvertState.STATUE_FILE_ERROR,  ConvertState.STATUS_ERROR
  })
  @Retention(RetentionPolicy.SOURCE)
  public @interface ConvertState{
    String STATUS_READY="就绪";
    String STATUS_CONVERTING="正在转换";
    String STATUS_COMPLETE="完成";
    String STATUS_ERROR="失败";
    String STATUE_FILE_ERROR="损坏";
    String STATUS_FORMAT="%s %%";
  }

  private M3u8File m3u8File;

  private IParser parserImpl;

  public M3u8Parser(M3u8File m3u8File) throws IOException {
    this.m3u8File=m3u8File;
    getM3u8Info();
    readM3u8File(m3u8File.fullPath);
    m3u8File.setM3u8Frames();
  }

  /**
   * 解析M3u8信息
   */
  public void getM3u8Info(){
    try {
      //使用ffmpeg的retrieveInfo函数解析第一个分片视频的信息
      //不管是m3u8文件还是视频文件，都直接用这个函数解析
      String info = FfmpegM3u8Jni.retrieveInfo(m3u8File.fullPath);
      LogUtil.d(m3u8File.fullPath+" , M3u8File: " + info);
      //Log.d(fullPath, "this.videoList.get(0) "+this.videoList.get(0));
      JSONObject jsonObject = new JSONObject(info);
      m3u8File.rotation = jsonObject.getInt("rotation");
      m3u8File.width = jsonObject.getInt("width");
      m3u8File.height = jsonObject.getInt("height");
      m3u8File.timeLength = jsonObject.getInt("duration");//返回毫秒
      m3u8File.fps = jsonObject.getInt("fps");
      m3u8File.videoCodec = jsonObject.getString("videoCodec");
    } catch (Exception e) {
      m3u8File.status = ConvertState.STATUE_FILE_ERROR;
      LogUtil.e(e.getMessage());
    }
  }

  /**
   * 读取 M3u8文件
   * @param path
   */
  public void readM3u8File(String path){
    FileReader reader = null;
    BufferedReader br = null;
    try {
      reader = new FileReader(path);
      br = new BufferedReader(reader);
      //如果不以#EXTM3U则格式错误
      String line = br.readLine();
      if (!line.startsWith("#EXTM3U")) {
        LogUtil.d( "M3u8File: file not start with #EXTM3U");
        return;
      }
      while ((line = br.readLine()) != null) {
        if (line.startsWith("#EXTINF:")) {
          m3u8File.videoList.add(br.readLine());
        }
        /*m3u8文件结束符*/
        else if (line.startsWith("#EXT-X-ENDLIST")) {
          break;
        }
      }
    } catch (Exception e) {
      m3u8File.status = ConvertState.STATUE_FILE_ERROR;
      LogUtil.e(e.getMessage());
    } finally {
      try{ br.close();}catch (Exception e){}
      try{ reader.close();}catch (Exception e){}
    }
  }


  private class ConvertProgress implements Runnable{
    private final ConvertListener mListener;
    public ConvertProgress(ConvertListener listener){
      mListener=listener;
    }

    @Override
    public void run() {
//      while (parserImpl.getProgress() == 0)
//        ;
      mListener.onStart();
      for (; ; ) {
        if (parserImpl.getProgress() == 0) {
          mListener.onStop();
          return;
        }
        //Log.d("isWorking:", "getprogress: "+String.valueOf(getProgress()));
        mListener.onProgress(parserImpl.getProgress());
        try {
          Thread.sleep(500);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
  }

  private class ConvertThread implements Runnable{

    private final String[] fileOrCmd;
    public ConvertThread(String [] fileOrCmd){
      this.fileOrCmd=fileOrCmd;
    }

    @Override
    public void run() {
      try {
        parserImpl.parserM3u8(fileOrCmd);
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }
  }

  public void startConvert(@ConvertType int type ,ConvertListener listener){
    if (!m3u8File.isChecked) {
        return;
    }
    //ffmpeg -allowed_extensions ALL -i index.m3u8 -c copy new.mp4
    File f = new File(m3u8File.convertedFullPath);
    if (f.exists()) {
      f.delete();
    }
    String[] fileOrCmds;
    //使用ffmpeg进行转码
    if (type==ConvertType.TYPE_FFMPEG) {
      // 拼接ffmpeg命令
      fileOrCmds =new String[]{"ffmpeg", "-allowed_extensions", "ALL", "-i", m3u8File.fullPath, "-c", "copy", m3u8File.convertedFullPath};
      LogUtil.d( "FFmpegCmd run: " + fileOrCmds);
      parserImpl=new FfmpegM3u8Parser();
    }
    //使用java进行转码
    else {
      fileOrCmds=new String[]{m3u8File.fullPath};
      parserImpl=new JavaParser();
    }
    new Thread(new ConvertProgress(listener)).start();
    new Thread(new ConvertThread(fileOrCmds)).start();
  }

  public interface ConvertListener {

    void onProgress(long progress);

    void onStart();

    void onStop();
  }

  //删除旧的m3u8文件
  public void deleteOldFiles() {
    boolean canDel = true;
    for (int i = 0; i < m3u8File.videoList.size(); i++) {
      if (!m3u8File.videoList.get(i).startsWith(m3u8File.prefix)) {
        canDel = false;
        break;
      }
    }
    File m3u8Dir = new File(m3u8File.prefix);
    File m3u8Fl = new File(m3u8File.fullPath);
    if (canDel && m3u8Dir.exists() && m3u8Fl.exists()) {
      m3u8Dir.delete();
      m3u8Fl.delete();
    } else {
      LogUtil.d("deleteOldFiles: can't delete old file");
    }
  }


}
